package administracion.managedBean.productos;

import Entities.Especial;
import ejb.EspecialFacadeLocal;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.imageio.ImageIO;
import javax.servlet.ServletContext;
import listasGenericas.CategoriasEnum;
import org.primefaces.context.RequestContext;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.UploadedFile;
import sesion.PermisoPagina;
import tablemodel.GeneralLazyModel;
import util.PageCodeGenerico;

/**
 * Clase que maneja el page code la pagina de especiales
 */
@ManagedBean
@ViewScoped
public class PCEspecial extends PageCodeGenerico implements Serializable {

    @EJB
    private EspecialFacadeLocal entidadFacade;
    private LazyDataModel<Especial> listado;
    private Especial temporal;
    private Properties colsVisible;
    private Map<String, String> checksVisible;
    private List<String> selectedChecksVisible;
    private Accion accion = Accion.CREAR;
    private SelectItem[] estados;
    private static List<SelectItem> categorias;
    private UploadedFile file;
    private String workingDir;
    private String imagenSrc;
    private String imagen;

    /**
     * Creates a new instance of EspecialBean
     */
    public PCEspecial() {
        super();
        this.listado = new GeneralLazyModel<>(new Especial());
        this.temporal = new Especial();
        this.colsVisible = new Properties();
        ServletContext strv = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
        workingDir = (String) strv.getRealPath("/upload/");
//        System.out.println(workingDir);

    }

    public String getWorkingDir() {
        return workingDir;
    }

    public void setWorkingDir(String workingDir) {
        this.workingDir = workingDir;
    }

    /**
     * Seteo la imagen y su url para obtener luego
     *
     * @return
     */
    public String getImagenSrc() {

        if (this.temporal.getImagen() != null) {
            this.imagenSrc = this.workingDir + this.temporal.getImagen();
            System.out.println("imagenSrc" + imagenSrc);
        }
        return imagenSrc;
    }

    public void setImagenSrc(String imagenSrc) {
        this.imagenSrc = imagenSrc;
    }

    /**
     * Reinicializo las columnas seleccionables.
     *
     */
    @PostConstruct
    public void reinicializarChecks() {
        this.checksVisible = new HashMap<>();
        this.checksVisible.put("Id", "id");
        this.checksVisible.put("Descripción Corta", "descripcionCorta");
        this.checksVisible.put("Descripción Larga", "descripcionLarga");
        this.checksVisible.put("Descripción Especial", "descripcionEspecial");
        this.checksVisible.put("Categoria", "categoria");
        this.checksVisible.put("Precio", "precio");

        this.selectedChecksVisible = new ArrayList<>();
        this.selectedChecksVisible.add("id");
        this.selectedChecksVisible.add("descripcionCorta");
        this.selectedChecksVisible.add("descripcionLarga");
        this.selectedChecksVisible.add("descripcionEspecial");
        this.selectedChecksVisible.add("categoria");
        this.selectedChecksVisible.add("precio");

    }

    public UploadedFile getFile() {

        return file;
    }

    public void setFile(UploadedFile file) {
        this.file = file;
    }

    public String imprimirEstado(Boolean estado) {
        if (estado == true) {
            return "Activo";
        } else {
            return "Inactivo";
        }
    }

    public SelectItem[] getEstados() {
        return estados;
    }

    public void setEstados(SelectItem[] estados) {
        this.estados = estados;
    }

    public List<SelectItem> getCategorias() {
        if (categorias == null) {
            categorias = new ArrayList<>();
            for (CategoriasEnum o : CategoriasEnum.values()) {
                SelectItem i = new SelectItem();
                i.setLabel(o.name());
                i.setDescription(o.name());
                i.setValue(o.getCod());
                categorias.add(i);
            }
        }

        return categorias;
    }

    public static void setCategorias(List<SelectItem> categorias) {
        PCEspecial.categorias = categorias;
    }

    public String devolverTituloDlg() {
        switch (this.accion) {
            case CREAR:
                return "Crear";
            case EDITAR:
                return "Editar";
            default:
                return "";
        }
    }

    public PermisoPagina consultarPermisos() {
        if (getMi_sesion() != null) {
            return getMi_sesion().consultarPermisos(Especial.class);
        } else {
            return new PermisoPagina();
        }
    }

    public String devolverTxtBtnCancelarDlg() {
        switch (this.accion) {
            case VER:
                return "Cerrar";
            default:
                return "Cancelar";
        }
    }

    public String devolverTxtLimpiarFormDlg() {
        switch (this.accion) {
            case EDITAR:
                return "Restablecer formulario";
            default:
                return "Limpiar formulario";
        }
    }

    public boolean esCrear() {
        return this.accion == Accion.CREAR;
    }

    public boolean esEditar() {
        return this.accion == Accion.EDITAR;
    }

    public boolean esVer() {
        return this.accion == Accion.VER;
    }

    /**
     * Seteo las columnas visibles.
     */
    public void setearVisibles() {
        if (checksVisible != null && !checksVisible.isEmpty()) {
            for (Map.Entry<String, String> entry : checksVisible.entrySet()) {
                String valor = entry.getValue();
                boolean existe = false;
                if (selectedChecksVisible != null && !selectedChecksVisible.isEmpty()) {
                    for (Iterator<String> it = selectedChecksVisible.iterator(); it.hasNext();) {
                        String colSel = it.next();
                        if (colSel.trim().toLowerCase().equals(valor.trim().toLowerCase())) {
                            existe = true;
                            break;
                        }
                    }
                } else {
                    setearError("Debe seleccionar al menos una columna");
                    break;
                }
                this.colsVisible.put(valor, existe);
            }
        } else {
            setearError("Debe seleccionar al menos una columna");
        }
    }

    public LazyDataModel<Especial> getListado() {
        if (consultarPermisos().isVer()) {
            return listado;
        } else {
            return null;
        }
    }

    public void setListado(LazyDataModel<Especial> listado) {
        this.listado = listado;
    }

    public Especial getTemporal() {
        return temporal;
    }

    public void setTemporal(Especial temporal) {
        this.temporal = temporal;
    }

    public Map<String, String> getChecksVisible() {
        return checksVisible;
    }

    public void setChecksVisible(Map<String, String> checksVisible) {
        this.checksVisible = checksVisible;
    }

    public List<String> getSelectedChecksVisible() {
        return selectedChecksVisible;
    }

    public void setSelectedChecksVisible(List<String> selectedChecksVisible) {
        this.selectedChecksVisible = selectedChecksVisible;
    }

    public void reinicializarTemporal() {
        this.temporal = new Especial();
        this.accion = Accion.CREAR;
        super.getMi_sesion().setDirImagen(null);
    }

    public void establecerTemporal(Especial objeto, boolean isEditar) {
        this.temporal = (objeto == null) ? new Especial() : objeto;
        this.accion = (isEditar) ? Accion.EDITAR : Accion.VER;
        super.getMi_sesion().setDirImagen(workingDir + "\\" + this.temporal.getImagen());
    }

    public void reinicializarColsVisible() {
        this.colsVisible.clear();
    }

    /**
     *
     * @param col Sin tildes ni espacios y en minúsculas
     * @param visible
     */
    public void establecerColVisible(String col, boolean visible) {
        this.colsVisible.put(col, visible);
    }

    /**
     *
     * @param col Sin tildes ni espacios y en minúsculas
     * @return
     */
    public boolean getColVisible(String col) {
        boolean resp = true;
        if (this.colsVisible.get(col) != null) {
            try {
                resp = (boolean) this.colsVisible.get(col);
            } catch (Exception e) {
            }
        }
        return resp;
    }

    /**
     * Elimino un especial de la casa
     */
    public void eliminar() {
        if (consultarPermisos().isBaja()) {
            if (this.temporal != null) {
                try {
                    entidadFacade.eliminar(this.temporal);
                    setearInfo("Operación finalizada correctamente.");
                } catch (Exception e) {
                    setearError(e);
                }
            } else {
                setearInfo("Nada que eliminar.");
            }
        } else {
            setearError("No tiene permisos suficientes para ejecutar esta acción");
        }
    }

    public boolean guardar(String mi_param) {
        switch (this.accion) {
            case CREAR:
                return crear(mi_param);
            case EDITAR:
                return modificar(mi_param);
            default:
                return false;
        }
    }

    /**
     * Funcion que una vez subido el archivo lo escribe en disco.
     */
    public void escribirEnDisco() {

        try {
            if (file != null) {
                //Tamanio de la imagen
                int dstWidth = 620;
                int dstHeight = 384;

                workingDir = workingDir + this.temporal.getImagen();
                BufferedImage srcImage = ImageIO.read(file.getInputstream());
                BufferedImage dstImage = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_RGB);
                dstImage.getGraphics().drawImage(srcImage, 0, 0, dstWidth, dstHeight, null);
                ImageIO.write(dstImage, "jpg", new File(workingDir));
            }
        } catch (IOException ex) {
            Logger.getLogger(PCEspecial.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Manejo la subida de archivos
     */
    public void upload(FileUploadEvent evt) {
        file = evt.getFile();
        //  this.imagen = (Image) file;
        Date d = new Date();
        d.getTime();
        String fechaHoy = this.getMi_sesion().getNombreUsuario() + d.getTime() + ".jpg";
        //get uploaded file from the event
        UploadedFile uploadedFile = (UploadedFile) evt.getFile();

        //create destination File

        //use org.apache.commons.io.FileUtils to copy the File
        try {
            //create an InputStream from the uploaded file
            InputStream inputStr = uploadedFile.getInputstream();
            String destPath = workingDir + "\\" + fechaHoy;
            File destFile = new File(destPath);
            OutputStream outputStream =
                    new FileOutputStream(destFile);
            int read;
            byte[] bytes = new byte[30000];

            while ((read = inputStr.read(bytes)) != -1) {
                outputStream.write(bytes, 0, read);
            }
            super.getMi_sesion().setDirImagen(destPath);
            this.imagen = fechaHoy;
            FacesMessage msg = new FacesMessage("El archivo " + evt.getFile().getFileName() + " se subió correctamente.");
            FacesContext.getCurrentInstance().addMessage(null, msg);

        } catch (IOException e) {
            e.printStackTrace();
            this.imagen = null;
            FacesMessage msg = new FacesMessage("Error al subir el archivo");
            FacesContext.getCurrentInstance().addMessage(null, msg);
            //log error
        }
    }

    /**
     * Modifico un especial
     *
     * @param mi_param
     * @return
     */
    private boolean modificar(String mi_param) {
        if (consultarPermisos().isModificacion()) {
            try {
                if (this.imagen != null) {
                    this.temporal.setImagen(this.imagen);
                }
                String codigo = String.valueOf(this.temporal.getId());
                entidadFacade.editar(this.temporal);
                setearInfo("Modificación exitosa " + "de " + mi_param + " con código: " + codigo);
                RequestContext.getCurrentInstance().addCallbackParam("correcto", true);
                RequestContext.getCurrentInstance().addCallbackParam("param", mi_param);
                return true;
            } catch (Exception e) {
                setearError(e);

                RequestContext.getCurrentInstance().addCallbackParam("correcto", false);
                RequestContext.getCurrentInstance().addCallbackParam("param", mi_param);
                return false;
            }
        } else {
            return false;
        }
    }

    private boolean crear(String mi_param) {
        if (consultarPermisos().isAlta()) {
            try {
                if (this.imagen != null) {
                    this.temporal.setImagen(this.imagen);
                }
                entidadFacade.crear(this.temporal);
//                escribirEnDisco();
                setearInfo("Se ha creado " + "exitosamente un nuevo " + mi_param);
                RequestContext.getCurrentInstance().addCallbackParam("correcto", true);
                RequestContext.getCurrentInstance().addCallbackParam("param", mi_param);
                return true;
            } catch (Exception e) {
                setearError(e);
                RequestContext.getCurrentInstance().addCallbackParam("correcto", false);
                RequestContext.getCurrentInstance().addCallbackParam("param", mi_param);
                return false;
            }
        } else {
            return false;

        }
    }

    public enum Accion {

        CREAR, EDITAR, VER;
    }
}
